﻿using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectSound;
using System;
using System.Collections;
using System.Drawing;
using System.IO;

namespace WiiShooter
{
    public struct Wall
    {
        public Vector3 vertex1;
        public Vector3 vertex2;
        public Vector3 vertex3;
        public Vector3 vertex4;
        public Wall(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4)
        {
            vertex1 = v1;
            vertex2 = v2;
            vertex3 = v3;
            vertex4 = v4;
        }
       
    }

    class LevelLoader
    {
        private Microsoft.DirectX.Direct3D.Device device;
        //list of the walls and their 4 coordinates
        public ArrayList wallList = new ArrayList();
        public ArrayList wallListTextured = new ArrayList();
        //public CustomVertex.PositionColored[] verticesArray;
        //public CustomVertex.PositionNormalTextured[] verticesTextured;
        public ArrayList textureList = new ArrayList();
        public ArrayList textures = new ArrayList();
        public Entity[][] levelStages;
        public Entity thePlayer;
        //sound device
        private Microsoft.DirectX.DirectSound.Device soundDevice;
        public int currentStage;
        
        //Vertex stuffs
        /*public VertexBuffer vb;
        public VertexBuffer vb2;*/

        public LevelLoader(ref Microsoft.DirectX.Direct3D.Device devicePass, Game gamePass,
            ref Microsoft.DirectX.DirectSound.Device soundDevicePass)
        {
            device = devicePass;
            soundDevice = soundDevicePass;
            readFile("level.csv");
            setMasterWallLists();
            LoadTexturesAndMaterials();
        }
        
        /**
         * readFile - Reads text from a file.
         */
        public void readFile(string FileName)
        {
            StreamReader objReader = new StreamReader(FileName);
            string sLine = "";
            string textureName = "";
            string entName = "";
            float x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, u, v;
            int pathSize;
            float angle;

            /* start reading the text file */
            while(sLine != null) 
            {
                sLine = objReader.ReadLine();
                if(sLine != null && !sLine.StartsWith("#")) {
                    if(sLine.StartsWith("RGB") || sLine.StartsWith("TEX")){  //read wall/floor/ceiling info
                        string[] inputs = sLine.Split(',');
                        x1 = float.Parse(inputs[1]);
                        y1 = float.Parse(inputs[2]);
                        z1 = float.Parse(inputs[3]);
                        x2 = float.Parse(inputs[4]);
                        y2 = float.Parse(inputs[5]);
                        z2 = float.Parse(inputs[6]);
                        x3 = float.Parse(inputs[7]);
                        y3 = float.Parse(inputs[8]);
                        z3 = float.Parse(inputs[9]);
                        x4 = float.Parse(inputs[10]);
                        y4 = float.Parse(inputs[11]);
                        z4 = float.Parse(inputs[12]);
                        u = float.Parse(inputs[13]);
                        v = float.Parse(inputs[14]);
                        textureName = inputs[15];
                        // Solid color wall with color RGB.
                        if(inputs[0].Equals("RGB")) {
                            makeLevel(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, u, v, textureName, 0);
                        // Textured wall.
                        } else if(inputs[0].Equals("TEX")) {
                            makeLevel(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, u, v, textureName, 1);
                        }
                    // Entity.
                    } else if(sLine.StartsWith("PLAYER")) {
                        string[] inputs = sLine.Split(',');
                        entName = inputs[1];                        
                        pathSize = int.Parse(inputs[2]);
                        angle = float.Parse(inputs[3]);
                        float[,] pathNode = new float[pathSize,6];
                        for (int i = 0; i < pathSize; i++)
                        {
                            sLine = objReader.ReadLine();
                            string[] path = sLine.Split(',');
                            pathNode[i, 0] = float.Parse(path[0]);
                            pathNode[i, 1] = float.Parse(path[1]);
                            pathNode[i, 2] = float.Parse(path[2]);
                            pathNode[i, 3] = float.Parse(path[3]);
                            pathNode[i, 4] = float.Parse(path[4]);
                            pathNode[i, 5] = float.Parse(path[5]);
                        }
                        MakeEntity(entName, pathNode, angle);
                    } else if(sLine.StartsWith("LEVEL")) {
                        string[] inputs = sLine.Split(',');
                        levelStages = new Entity[int.Parse(inputs[1])][];
                    } else if(sLine.StartsWith("STAGE")) {
                        string[] inputs = sLine.Split(',');
                        int stageNum = int.Parse(inputs[1]);
                        int stageNumAdjusted = stageNum - 1;
                        int numEnemies = int.Parse(inputs[2]);
                        levelStages[stageNumAdjusted] = new Entity[numEnemies];
                        for(int i = 0; i < numEnemies; i++) 
                        {
                            sLine = objReader.ReadLine();
                            if(sLine.StartsWith("ENT")) {
                                string[] inputs2 = sLine.Split(',');
                                entName = inputs2[1];
                                pathSize = int.Parse(inputs2[2]);
                                angle = float.Parse(inputs2[3]);
                                float[,] pathNode = new float[pathSize, 6];
                                for(int j = 0; j < pathSize; j++)
                                {
                                    sLine = objReader.ReadLine();
                                    string[] path = sLine.Split(',');
                                    pathNode[j, 0] = float.Parse(path[0]);
                                    pathNode[j, 1] = float.Parse(path[1]);
                                    pathNode[j, 2] = float.Parse(path[2]);
                                    pathNode[j, 3] = float.Parse(path[3]);
                                    pathNode[j, 4] = float.Parse(path[4]);
                                    pathNode[j, 5] = float.Parse(path[5]);
                                }
                                levelStages[stageNumAdjusted][i] = new Entity(pathNode, entName, ref device, angle, ref soundDevice);
                                //MakeEntity(entName, pathNode, angle);
                            }
                        }

                    }
                }
            }
            objReader.Close();
            /*
            foreach (Wall w in wallList)
            {
                Console.WriteLine(w.vertex1.ToString());
                Console.WriteLine(w.vertex2.ToString());
                Console.WriteLine(w.vertex3.ToString());
                Console.WriteLine(w.vertex4.ToString());
            }
             */
        }

        /**
         * Create the walls, floors, and ceilings
         */ 
        private void makeLevel(float x1, float y1, float z1,
                      float x2, float y2, float z2,
                      float x3, float y3, float z3,
                      float x4, float y4, float z4, float u, float v,
                      string someString, int which)
        {
            // Create the vector of three floats.
            Vector3 vector3one = new Vector3(x1, y1, z1);
            Vector3 vector3two = new Vector3(x2, y2, z2);
            Vector3 vector3three = new Vector3(x3, y3, z3);
            Vector3 vector3four = new Vector3(x4, y4, z4);
            Vector3 vector3positionNormal = new Vector3(0, 0, 1f);
            Wall w = new Wall(vector3one, vector3two, vector3three, vector3four);
            wallList.Add(w);
          /*  if (which == 0)  //solid color wall
            {
                Color wallColor = Color.FromName(someString);
                // The first triangle.
                wallList.Add(new CustomVertex.PositionColored(x1, y1, z1, wallColor.ToArgb()));
                wallList.Add(new CustomVertex.PositionColored(x2, y2, z2, wallColor.ToArgb()));
                wallList.Add(new CustomVertex.PositionColored(x3, y3, z3, wallColor.ToArgb()));

                // The second triangle.
                wallList.Add(new CustomVertex.PositionColored(x1, y1, z1, wallColor.ToArgb()));
                wallList.Add(new CustomVertex.PositionColored(x3, y3, z3, wallColor.ToArgb()));
                wallList.Add(new CustomVertex.PositionColored(x4, y4, z4, wallColor.ToArgb()));
            }*/
            if (which == 1)  //textured
            {
                ArrayList temp = new ArrayList();

                // Triangle one.
                temp.Add(new CustomVertex.PositionNormalTextured(vector3four, vector3positionNormal, 0, 0));
                temp.Add(new CustomVertex.PositionNormalTextured(vector3one, vector3positionNormal, 0, v));
                temp.Add(new CustomVertex.PositionNormalTextured(vector3two, vector3positionNormal, u, v));

                // Triangle two.
                temp.Add(new CustomVertex.PositionNormalTextured(vector3two, vector3positionNormal, u, v));
                temp.Add(new CustomVertex.PositionNormalTextured(vector3four, vector3positionNormal, 0, 0));
                temp.Add(new CustomVertex.PositionNormalTextured(vector3three, vector3positionNormal, u, 0));

                textureList.Add(someString);
                wallListTextured.Add(temp);

                /*wallListTextured.Add(new CustomVertex.PositionNormalTextured(vector3four, vector3positionNormal, 0, 0));
                wallListTextured.Add(new CustomVertex.PositionNormalTextured(vector3one, vector3positionNormal, 0, v));
                wallListTextured.Add(new CustomVertex.PositionNormalTextured(vector3two, vector3positionNormal, u, v));

                wallListTextured.Add(new CustomVertex.PositionNormalTextured(vector3two, vector3positionNormal, u, v));
                wallListTextured.Add(new CustomVertex.PositionNormalTextured(vector3four, vector3positionNormal, 0, 0));
                wallListTextured.Add(new CustomVertex.PositionNormalTextured(vector3three, vector3positionNormal, u, 0));

                textureList.Add(someString);*/
            }
        }

        private void setMasterWallLists()
        {
            //verticesArray = (CustomVertex.PositionColored[])wallList.ToArray(typeof(CustomVertex.PositionColored));
            /*vb = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), wallListTextured.Count, device,
                Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Default);
            verticesTextured = (CustomVertex.PositionNormalTextured[])wallListTextured.ToArray(
                typeof(CustomVertex.PositionNormalTextured));

            vb.SetData(verticesTextured, 0, LockFlags.None);*/
        }

        private void MakeEntity(string name, float[,] path, float angle)
        {
            Entity entity = new Entity(path, name, ref device, angle, ref soundDevice);
            Game.entityList.Add(entity);
            if(name.Equals("Player.txt"))
            {
                thePlayer = entity;
            }
        }

        /**
         * LoadTexturesAndMaterials - TODO
         */
        private void LoadTexturesAndMaterials()
        {
            /*material = new Material();

            material.Diffuse = Color.White;
            material.Ambient = Color.White;
            material.SpecularSharpness = 15f;*/

            foreach (String t in textureList)
            {
                textures.Add(TextureLoader.FromFile(device, t));
            }
        }

    }
}
